#!/bin/sh /etc/rc.common
# Copyright (C) 2008-2020 OpenWrt.org
# Copyright (C) 2022 ImmortalWrt.org

START=99
USE_PROCD=0

dnsmasq_path="/tmp/dnsmasq.d"

start_firewall() {
    local cfg="$1"

    local type
    config_get type "$cfg" TYPE

    case "$type" in
    edge)
        local tunname ipaddr prefix gateway fwmark masquerade enabled edge_wifi roas global

        config_get tunname "$cfg" 'tunname'
        config_get ipaddr "$cfg" 'ipaddr'
        config_get prefix "$cfg" 'prefix'
        config_get gateway "$cfg" 'gateway'
        config_get fwmark "$cfg" 'fwmark'
        config_get masquerade "$cfg" 'masquerade'
        config_get enabled "$cfg" 'enabled'
        config_get edge_wifi "$cfg" 'edge_wifi'
        config_get roas "$cfg" 'roas'
        config_get global "$cfg" 'global'

        # todo default global
        [ -z "$global" ] && global="1"
        [ -z "$roas" ] && roas="0"

        [ "$enabled" = "0" ] && return 1

        # if edge_wifi is 100, set all interfaces to then one sdwan link, default br-lan
        [ "$edge_wifi" = "100" ] && {
            edge_wifi=""
        }

        # must be in here get values
        out="out$fwmark"
        vpnset="vpn$out"
        local_br_ifname="br-lan$edge_wifi"
        # vpnset_create=$(ipset list "$vpnset" -n)

        sed -i "/$out/d" /etc/iproute2/rt_tables
        echo "$fwmark $out" >>/etc/iproute2/rt_tables
        ip route del default via $gateway table $out dev "$tunname" 2>/dev/null
        ip route add default via $gateway table $out dev "$tunname" 2>/dev/null

        ip rule del fwmark "0x$fwmark" table $out 2>/dev/null
        ip rule add fwmark "0x$fwmark" table $out 2>/dev/null

        ipset create "$vpnset" hash:net 2>/dev/null
        ipset flush "$vpnset" 2>/dev/null

        iptables -t mangle -D PREROUTING -i "$local_br_ifname" -m set --match-set $vpnset dst -j MARK --set-mark "0x$fwmark" 2>/dev/null
        #iptables -t mangle -I PREROUTING -i "$local_br_ifname" -m set --match-set $vpnset dst -j MARK --set-mark "0x$fwmark" 2>/dev/null

        # add mark for local
        # iptables -t mangle -A OUTPUT -o "$local_br_ifname" -m set --match-set $vpnset dst -j MARK --set-mark "0x$fwmark" 2>/dev/null
        #iptables -t mangle -D OUTPUT -m set --match-set $vpnset dst -j MARK --set-mark "0x$fwmark" 2>/dev/null
        #iptables -t mangle -I OUTPUT -m set --match-set $vpnset dst -j MARK --set-mark "0x$fwmark" 2>/dev/null

        # support router on a stick
        [ "$roas" = "1" ] && {
            iptables -D FORWARD -i br-lan -j ACCEPT 2>/dev/null
            iptables -D FORWARD -o br-lan -j ACCEPT 2>/dev/null
            iptables -t nat -D POSTROUTING -o br-lan -j MASQUERADE 2>/dev/null
            iptables -t mangle -D OUTPUT -o br-lan -m set --match-set vpnout105 dst -j MARK --set-mark "0x$fwmark" 2>/dev/null

            iptables -I FORWARD -i br-lan -j ACCEPT 2>/dev/null
            iptables -I FORWARD -o br-lan -j ACCEPT 2>/dev/null
            iptables -t nat -I POSTROUTING -o br-lan -j MASQUERADE 2>/dev/null
            iptables -t mangle -I OUTPUT -o br-lan -m set --match-set vpnout105 dst -j MARK --set-mark "0x$fwmark" 2>/dev/null
        }

        echo "set dnsmasq"

        # create dnsmasq conf for every lan interface
        resolv_auot_path="$dnsmasq_path/lan$edge_wifi"
        rm -rf $resolv_auot_path
        mkdir -p "$resolv_auot_path" 2>/dev/null
        mkdir -p /tmp/resolv.conf.d 2>/dev/null
        touch "$resolv_auot_path/resolv.lan$edge_wifi.conf.auto" 2>/dev/null

        local INST="lan$edge_wifi"
        if [ "$global" != "1" ]; then
            uci delete dhcp.${INST}_dns="dnsmasq"
            uci set dhcp.${INST}_dns="dnsmasq"
            uci set dhcp.${INST}_dns.dhcpbogushostname="0"
            uci set dhcp.${INST}_dns.domainneeded="1"
            uci set dhcp.${INST}_dns.boguspriv="1"
            uci set dhcp.${INST}_dns.filterwin2k="0"
            uci set dhcp.${INST}_dns.localise_queries="1"
            uci set dhcp.${INST}_dns.rebind_protection="1"
            uci set dhcp.${INST}_dns.rebind_localhost="1"
            uci set dhcp.${INST}_dns.local="/${INST}/"
            uci set dhcp.${INST}_dns.domain="${INST}"
            uci set dhcp.${INST}_dns.expandhosts="1"
            uci set dhcp.${INST}_dns.nonegcache="0"
            uci set dhcp.${INST}_dns.authoritative="1"
            uci set dhcp.${INST}_dns.readethers="1"
            uci set dhcp.${INST}_dns.leasefile="/tmp/dhcp.leases.${INST}"
            uci set dhcp.${INST}_dns.resolvfile="/tmp/resolv.conf.d/resolv.conf.auto"
            uci set dhcp.${INST}_dns.nonwildcard="1"
            uci set dhcp.${INST}_dns.nohosts="1"
            uci set dhcp.${INST}_dns.noresolv="1"
            uci set dhcp.${INST}_dns.allservers="1"
            uci set dhcp.${INST}_dns.queryport="0"
            uci set dhcp.${INST}_dns.cachesize="2000"
            uci set dhcp.${INST}_dns.ednspacket_max="1232"
            uci set dhcp.${INST}_dns.confdir="$resolv_auot_path"
            # uci set dhcp.${INST}_dns.logqueries="1"
            # uci set dhcp.${INST}_dns.logfacility="/tmp/${INST}_dnsmasq.log"

            uci del_list dhcp.${INST}_dns.interface="${INST}"
            uci del_list dhcp.${INST}_dns.notinterface="loopback"
            uci add_list dhcp.${INST}_dns.interface="${INST}"
            uci add_list dhcp.${INST}_dns.notinterface="loopback"

            uci del_list dhcp.${INST}_dns.server="$gateway"
            uci del_list dhcp.${INST}_dns.server="119.29.29.29"
            uci add_list dhcp.${INST}_dns.server="$gateway"
            uci add_list dhcp.${INST}_dns.server="119.29.29.29"

            uci set dhcp.${INST}.instance="${INST}_dns"
            uci set dhcp.${INST}.interface="${INST}"

            uci delete dhcp.@dnsmasq[0].nohosts=1
            uci delete dhcp.@dnsmasq[0].noresolv=1
            uci delete dhcp.@dnsmasq[0].allservers=1
            uci delete dhcp.@dnsmasq[0].server
            uci set dhcp.@dnsmasq[0].disabled=1

            iptables -t mangle -D PREROUTING -i br-lan -j MARK --set-mark "0x$fwmark" 2>/dev/null
            iptables -t mangle -D PREROUTING -i br-lan -m set --match-set $vpnset dst -j MARK --set-mark "0x$fwmark" 2>/dev/null
            iptables -t mangle -I PREROUTING -i br-lan -m set --match-set $vpnset dst -j MARK --set-mark "0x$fwmark" 2>/dev/null
        else
            local br_lan_ip=$(ifconfig br-lan | awk 'NR==2{print $2}' | tr -d 'addr:\n')
            iptables -t mangle -D PREROUTING -i br-lan -d $br_lan_ip -j RETURN >/dev/null
            iptables -t mangle -I PREROUTING -i br-lan -d $br_lan_ip -j RETURN >/dev/null
            uci delete dhcp.${INST}_dns
            uci delete dhcp.lan.instance
            uci set dhcp.@dnsmasq[0].nohosts=1
            uci set dhcp.@dnsmasq[0].noresolv=1
            uci set dhcp.@dnsmasq[0].allservers=1
            uci set dhcp.@dnsmasq[0].disabled=1
            uci del_list dhcp.@dnsmasq[0].server="$gateway"
            uci del_list dhcp.@dnsmasq[0].server="$gateway"
            uci add_list dhcp.@dnsmasq[0].server="$gateway"
            uci add_list dhcp.@dnsmasq[0].server="$gateway"

            iptables -t mangle -D PREROUTING -i br-lan -m set --match-set $vpnset dst -j MARK --set-mark "0x$fwmark" 2>/dev/null
            iptables -t mangle -D PREROUTING -i br-lan -j MARK --set-mark "0x$fwmark" 2>/dev/null
            iptables -t mangle -I PREROUTING -i br-lan -j MARK --set-mark "0x$fwmark" 2>/dev/null
        fi

        uci commit dhcp

        echo "make ipset conf"
        # make ipset conf
        rm -f $dnsmasq_path/lan$edge_wifi/$vpnset.conf

        awk -v gateway=$gateway -v tunname=$tunname \
            '{print "server=/"$1"/"gateway"@"tunname}' /etc/sdwan_domain >$dnsmasq_path/lan$edge_wifi/$vpnset.conf

        awk -v vpnset=$vpnset '{print "ipset=/"$1"/"vpnset}' /etc/sdwan_domain >>$dnsmasq_path/lan$edge_wifi/$vpnset.conf

        # add extra ipset ips
        awk -v vpnset=$vpnset '!/^#/{print "add "vpnset" "$1}' /etc/extra_ipset_ips.txt >/tmp/$vpnset"_extra_ipset_ips.txt"
        ipset restore -f /tmp/$vpnset"_extra_ipset_ips.txt"
        rm -f /tmp/$vpnset"_extra_ipset_ips.txt"

        [ "$global" = "1" ] && {
            rm -f $dnsmasq_path/lan$edge_wifi/$vpnset.conf
        }

        echo "set edge done"
        ;;
    supernode)
        local port enabled
        config_get port "$cfg" 'port'
        config_get enabled "$cfg" 'enabled'

        [ "$enabled" = "0" ] && return 1

        iptables -D INPUT -p udp --dport $port -j ACCEPT -m comment --comment 'n2n supernode port' 2>/dev/null
        iptables -I INPUT -p udp --dport $port -j ACCEPT -m comment --comment 'n2n supernode port' 2>/dev/null
        ;;
    esac
}

stop_firewall() {
    local cfg="$1"

    local type
    config_get type "$cfg" TYPE

    case "$type" in
    edge)
        local tunname ipaddr prefix gateway fwmark edge_wifi

        config_get tunname "$cfg" 'tunname'
        config_get ipaddr "$cfg" 'ipaddr'
        config_get prefix "$cfg" 'prefix'
        config_get gateway "$cfg" 'gateway'
        config_get fwmark "$cfg" 'fwmark'
        config_get edge_wifi "$cfg" 'edge_wifi'

        local out="out$fwmark"
        local vpnset="vpn$out"

        # del route for gateway
        sed -i "/$out/d" /etc/iproute2/rt_tables

        ip route del default via $gateway table $out dev "$tunname" 2>/dev/null
        ip rule del fwmark "0x$fwmark" table $out 2>/dev/null

        #del mark for forward
        iptables -t mangle -D PREROUTING -i "$local_br_ifname" -m set --match-set $vpnset dst -j MARK --set-mark "0x$fwmark" 2>/dev/null

        # del mark for local
        # iptables -t mangle -D OUTPUT  -o ""$local_br_ifname -m set --match-set $vpnset dst -j MARK --set-mark "0x$fwmark" 2>/dev/null
        iptables -t mangle -D OUTPUT -m set --match-set $vpnset dst -j MARK --set-mark "0x$fwmark" 2>/dev/null

        # del vpn set
        ipset flush "$vpnset" 2>/dev/null
        ipset destroy "$vpnset" 2>/dev/null

        local local_br_ifname="br-lan$edge_wifi"

        # del ipset conf
        rm -rf $dnsmasq_path/lan$edge_wifi

        local INST="lan$edge_wifi"
        rm -f /var/etc/dnsmasq.conf.${INST}_dns
        uci delete dhcp.${INST}_dns
        uci commit dhcp

        ;;
    supernode)
        local port
        config_get port "$cfg" 'port'

        iptables -D INPUT -p udp --dport $port -j ACCEPT -m comment --comment 'n2n supernode port' 2>"/dev/null"
        ;;
    esac
}

start_service() {
    config_load 'n2n'
    config_foreach start_firewall 'edge'
    config_foreach start_firewall 'supernode'
}

stop_service() {
    config_load 'n2n'
    config_foreach stop_firewall 'edge'
    config_foreach stop_firewall 'supernode'
}

reload_service() {
    stop
    start
}

service_triggers() {
    procd_add_reload_trigger "sdwan_for_firewall"
}
